from typing import Union
from fastapi import APIRouter, Depends, Response
from sqlalchemy import and_, desc, or_
from sqlalchemy.orm import Session
from db import get_db, models
from schemas.order import OrderPagination, OrderDeliveryRequest, OrderModel, OrderPaginationRequest
from schemas.users import UserModel
from users.users import verify_token
from datetime import datetime
from utils.response import HTTPException

router = APIRouter(prefix="/order", tags=["订单管理"])


@router.post("/pagination", dependencies=[Depends(verify_token)],
             response_model=OrderPagination,
             response_model_exclude_none=True)
def get_order_pagination(data: OrderPaginationRequest,
                         db: Session = Depends(get_db)):
    offset = data.page - 1

    filter_params = []
    order_by = desc(models.Order.id)

    if data.kw is not None:
        filter_params.append(models.Order.order_code.like(f"%{data.kw}%"))
    if data.order_status == 1:
        filter_params.append(models.Order.status != 0)
    elif data.order_status == 2:
        filter_params.append(models.Order.status == 1)
        filter_params.append(models.Order.payment_status == 1)
    elif data.order_status == 3:
        filter_params.append(models.Order.status == 1)
        filter_params.append(models.Order.payment_status == 2)
        filter_params.append(models.Order.shipping_status == 1)
    elif data.order_status == 4:
        filter_params.append(models.Order.status == 1)
        filter_params.append(models.Order.payment_status == 2)
        filter_params.append(models.Order.shipping_status == 2)

    if data.presale is not None:
        filter_params.append(models.Order.presale == True)

    if data.flower is not None:
        filter_params.append(or_(
            *[models.Order.items.like(f"%\"{i}\",%") for i in data.flower]
        ))

    orders = db.query(models.Order).filter(and_(
        *filter_params
    )).order_by(order_by).offset(offset).limit(data.page_size).all()

    total = db.query(models.Order).filter(and_(
        *filter_params
    )).count()

    return OrderPagination(
        page=data.page,
        page_size=data.page_size,
        total=total,
        data=orders
    )


@router.get("/detail/{order_id}",
            response_model=OrderModel,
            response_model_exclude_none=True,
            dependencies=[Depends(verify_token)])
def get_order_detail(order_id: int,
                     db: Session = Depends(get_db)):
    return db.query(models.Order).get(order_id)


@router.patch("/delivery")
def delivery_order(data: OrderDeliveryRequest,
                   user: UserModel = Depends(verify_token),
                   db: Session = Depends(get_db)):
    order: Union[models.Order, None] = db.query(models.Order).filter(and_(
        models.Order.id == data.order_id,
        models.Order.status != 0
    )).first()

    if order is None:
        raise HTTPException(message="订单不存在")
    elif order.payment_status == 1 or order.payment_status == 3:
        raise HTTPException(message="订单未支付")
    else:
        delivery_person: models.DeliveryPerson = db.query(models.DeliveryPerson).get(data.delivery_person_id)

        if delivery_person is None:
            raise HTTPException(message="配送员不存在")

        order.delivery_person = {
            "id": delivery_person.id,
            "name": delivery_person.name,
            "phone": delivery_person.phone
        }

        order.updated_on = datetime.now()
        order.updated_by = user.id
        order.shipping_status = 2

        delivery_person.delivering += 1

        db.commit()

    return Response()


@router.patch("/complete/{order_id}")
def complete_order(order_id: int,
                   user: UserModel = Depends(verify_token),
                   db: Session = Depends(get_db)):
    order: Union[models.Order, None] = db.query(models.Order).filter(and_(
        models.Order.id == order_id,
        models.Order.status != 0
    )).first()

    if order is None:
        raise HTTPException(message="订单不存在")

    if order.payment_status != 2:
        raise HTTPException(message="订单未支付")

    order.updated_on = datetime.now()
    order.updated_by = user.id
    order.status = 2
    order.shipping_status = 3

    if order.delivery_person["id"]:
        delivery_person: models.DeliveryPerson = db.query(models.DeliveryPerson).get(order.delivery_person["id"])
        if delivery_person:
            delivery_person.delivering -= 1
            delivery_person.delivery_count += 1

    db.commit()

    return Response()


@router.patch("/close/{order_id}")
def close_order(order_id: int,
                user: UserModel = Depends(verify_token),
                db: Session = Depends(get_db)):
    order: Union[models.Order, None] = db.query(models.Order).filter(and_(
        models.Order.id == order_id,
        models.Order.status != 0
    )).first()

    if order is None:
        raise HTTPException(message="订单不存在")
    else:
        if order.status != 1 or order.payment_status != 1:
            raise HTTPException(message="订单状态异常")

        order.updated_on = datetime.now()
        order.updated_by = user.id
        if order.payment_status == 2:
            order.payment_status = 3

            for i in order.items:
                if i["flower"]:
                    flower = db.query(models.Flower).get(i["flower"]["id"])
                    flower.sales_count -= i["quantity"]

        order.status = 3
        db.commit()

    return Response()


@router.patch("/refund/{order_id}")
def refund_order(order_id: int,
                user: UserModel = Depends(verify_token),
                db: Session = Depends(get_db)):
    order: Union[models.Order, None] = db.query(models.Order).filter(and_(
        models.Order.id == order_id,
        models.Order.status != 0
    )).first()

    if order is None:
        raise HTTPException(message="订单不存在")
    else:
        order.updated_on = datetime.now()
        order.updated_by = user.id
        order.payment_status = 3
        order.status = 3

        for i in order.items:
            if i["flower"]:
                flower = db.query(models.Flower).get(i["flower"]["id"])
                flower.sales_count -= i["quantity"]

        if order.delivery_person["id"]:
            delivery_person: models.DeliveryPerson = db.query(models.DeliveryPerson).get(order.delivery_person["id"])
            if delivery_person:
                delivery_person.delivering -= 1

        db.commit()

    return Response()


@router.get("/stats")
def stats(db: Session = Depends(get_db)):
    data = db.query(
        models.Order.id,
        models.Order.created_on,
        models.Order.payment_date,
        models.Order.total_price
    ).filter(and_(
        models.Order.status.in_([1, 2]),
        models.Order.payment_status == 2
    )).all()

    return [
        {
            "id": item.id,
            "created_on": item.created_on,
            "payment_date": item.payment_date,
            "total_price": item.total_price,
        } for item in data
    ]
